package sp.controller.platform;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import sp.pojo.User;
import sp.util.constant.GenerateCodeUtil;
import sp.util.constant.SysConstant;
import sp.util.mail.MailUtils;
import sp.util.vcode.VcodeUtil;
import sp.util.vcode.VerifyCode;


@Controller
@RequestMapping("/sp")
public class LoginController extends BaseController{
	
	@RequestMapping(value = "/login.action", method = RequestMethod.GET)
	public String getLoginPage() {
		log.debug("登录页面--->");
		return "platform/login";
	}
	
	
	//@CrossOrigin(origins = "http://localhost:8888")  跨域
	@ResponseBody
	@RequestMapping(value = "/dologin.action")
	public Map<String, String> doUserLogin(@RequestParam("username") String uname
			, @RequestParam("password") String password
			, @RequestParam(value="vcode", required=false) String vcode
			, HttpSession session){
		log.debug("登录验证开始...");
		Map<String, String> msg = new HashMap<String, String>();
		
		//验证码校验
		if (!getRedisApi().keyExist("validateCode")) {
			msg.put(SysConstant.ERROR, "验证码已过期");
			return msg;
		}
		String validateCode = getRedisApi().getStringKey("validateCode");
		VcodeUtil.checkVeifyCode(validateCode, vcode);
		
		
		//验证登录用户
		Subject currentUser = SecurityUtils.getSubject();
		//如果没有登录 进行验证
		try{
			if(!currentUser.isAuthenticated()) {
				//System.out.println("db密码" + getUserService().findUserByName(uname).getPassword());
				UsernamePasswordToken token = new UsernamePasswordToken(uname, password);
				currentUser.login(token);
				session.setAttribute("username", uname);
			} 	
		}catch (IncorrectCredentialsException  e1) {
			System.err.println("用户名或密码错误");
			msg.put(SysConstant.ERROR, "用户名或密码错误");
			return msg;
		} 
	
		msg.put(SysConstant.SYS_MSG, "success");
		return msg;
	}
	
	
	/**
	 * 获得注册页面
	 * @param user
	 * @return
	 */
	@RequestMapping(value = "/regist.action", method = RequestMethod.GET)
	public String getRegistPage(@ModelAttribute User user) {
		log.debug("注册页面----->");
		
		return "platform/regist";
	}
	
	
	/**
	 * 注册业务验证
	 * @param user
	 * @return
	 * @throws Exception 
	 */
	@ResponseBody
	@RequestMapping(value = "/doregist.action", method = RequestMethod.POST)
	public Map<String, String> doRegist(User user, HttpSession session) throws Exception {
		log.debug("注册--->业务验证");
		Map<String, String> map = new HashMap<>();
		
		User dbUser = getUserService().findUserByName(user.getTypeCode());
		if (dbUser != null) {
			if (dbUser.getIsStart() == 1) {
				map.put(SysConstant.SYS_MSG, "exist-active");//该账号已经注册过了!请重新填写
			} else {
				//可以处理重新获取激活码
				map.put(SysConstant.SYS_MSG, "exist-unactive");//该账号已注册,但未激活
			}
			return map;
		}
		
		//激活码:(activeCode:+typeCode)
		String key = "activeCode:" + user.getTypeCode();
		
		//刷新,防止数据库删除用户后 没有及时清理和该用户匹配的相关缓存
		if (getRedisApi().keyExist(key)) {
			getRedisApi().delKey(key);
			//清理和该key绑定的缓存: hasactive
			String keybind = "hasactive" + user.getTypeCode();
			if (getRedisApi().keyExist(keybind)) {
				getRedisApi().delKey(keybind);
			}
		}
		
				
		//发送内容
		StringBuffer emailMsg = new StringBuffer("<html><head></head><body><h1>您好 O(∩_∩)O, 欢迎您使用&lt;&lt;淘书&gt;&gt;注册!<h1>");
		String activeUrl = String.format("http://localhost:8888/SecondPlatform/sp/email-active.action?email=%s&&activecode=%s", user.getTypeCode(), getAccessCode(key));
		emailMsg.append("<h1>请点击以下链接激活账号,30分钟内有效!</h1>")
				.append("<h3><a href='").append(activeUrl).append("' >")
				.append(activeUrl).append("</a></h3></body></html>");
		//发送邮件
		MailUtils.sendMail(user.getTypeCode(), emailMsg.toString());
		
		//补充用户信息
		user.setIsStart(0);
		user.setEmail(user.getTypeCode());
		user.setCreateDate(new Date(System.currentTimeMillis()));
		//授予可登录游客权限
		user.setRoleId(2);
		
		//保存用户
		if (getUserService().txsaveUser(user)) {
			log.info("注册成功! 用户:" + user.getTypeCode());
			map.put(SysConstant.SYS_MSG, "success");//注册成功,请前往邮箱激活账号
		} else {
			log.debug("注册失败........");
			map.put(SysConstant.SYS_MSG, "fail");	//注册失败
		}
		
		return map;
		
	}
	
	
	/**
	 * 邮箱激活
	 * @return
	 */
	@RequestMapping(value = "email-active.action", method = RequestMethod.GET)
	public String activeCode(Model model, HttpServletRequest request,
			@RequestParam("activecode") String activecode, @RequestParam("email") String email) {
		log.debug("激活邮箱--->" + email);
		try {
			//从redis中获得激活码
			String code = getRedisApi().getStringKey("activeCode:" + email);
			
			if (code == null) {
				request.setAttribute(SysConstant.SYS_MSG, "expire");
				
				return "platform/activesuccess";
			}
			
			//避免重复激活
			if (getRedisApi().keyExist("hasactive" + email)) {
				request.setAttribute(SysConstant.SYS_MSG, "hasactive");
				return "platform/activesuccess";
			}
			
			//判断激活码 是否过期 以及是否匹配
			if (null != activecode && activecode.equals(code)) {
				log.debug("激活码有效, 开始激活....");
				//开始激活
				if (getUserService().txactiveEmail(email)) {
					log.debug("激活成功!");
					getRedisApi().set("hasactive" + email, "hasactive", SysConstant.EXPIRE_IN);
					model.addAttribute(SysConstant.SYS_MSG, "success");
					model.addAttribute("redirect-url", "/sp/login.action");
				} else {
					log.debug("激活码不匹配邮箱账号!");
					request.setAttribute(SysConstant.SYS_MSG, "email-noexist");
				}
			} else {
				log.debug("激活码错误!");
				request.setAttribute(SysConstant.SYS_MSG, "fail");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			request.setAttribute(SysConstant.SYS_MSG, "fail");
		}
		return "platform/activesuccess";
	}
 	
	
	
	
	
	/**
	 * 生成验证码
	 * @param response
	 * @param session
	 * @throws Exception
	 */
	@RequestMapping(value = "verifycode.action", method=RequestMethod.GET)
	public void verifyCode(HttpServletResponse response, HttpSession session) throws Exception {
		//设置浏览器不缓存
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		//将验证码输出到客户端
		response.setContentType("image/jpeg");

		String code = VerifyCode.generateVerifyCode(4);
		//合法的验证码
		//session.setAttribute("validateCode", code);
		//3分钟有效期
		getRedisApi().set("validateCode", code, 180);
		
		
		ServletOutputStream outputStream = response.getOutputStream();
		try{
			VerifyCode.outputImage(105, 30, outputStream, code);
		} catch (Exception e) {
			log.error("验证码错误");
			throw new RuntimeException("系统繁忙,请稍后再试");
		} finally {
			if (outputStream != null) {
				outputStream.flush();
				outputStream.close();
			}
		}
		
	}
	
	
	/**
	 * 退出
	 * @return
	 */
	@RequestMapping(value ="loginout.action", method = RequestMethod.GET)
	public String loginOut(){
		log.debug("用户注销---->");
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return "redirect:/sp/login.action";
	}
	
	
	

	/**
	 * 获得生成的激活码
	 * @param key
	 * @param email
	 * @return
	 */
	private  String getAccessCode(String key) {
		//激活码不存在或者未设置过期时间都会重新获取激活码
		if (isExpired(key)) {
			//30分钟有效期
			getRedisApi().set(key, GenerateCodeUtil.getActiveCode(), SysConstant.EXPIRE_IN);
		}
		return getRedisApi().getStringKey(key);
	}
	
	/**
	 * 判断激活码是否过期
	 * @param key
	 * @return
	 */
	private boolean isExpired(String key) {
		System.out.println("exist:" + getRedisApi().keyExist(key)  +" ttl:" + getRedisApi().ttl(key));
		if (!getRedisApi().keyExist(key) || getRedisApi().ttl(key) < 0) {
			return true;
		}
		return false;
	}
	
	
	
}
